<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  

  
  <title>闭包 | 前端日常</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
  <meta name="description" content="JS中的执行上下文，作用域链和闭包一, 执行上下文概念  当前代码的执行环境 执行上下文的三种类型： 全局执行上下文：全局执行环境是最外围的一个执行环境，在浏览器的全局对象是 window, this指向这个对象 函数执行上下文：可以有无数个，函数被调用的时候会被创建。每次调用函数都会创建一个新的执行上下文。 eval执行上下文，很少用。  每个执行上下文都有三个重要属性 1, 变量对象    2">
<meta property="og:type" content="article">
<meta property="og:title" content="闭包">
<meta property="og:url" content="https://coloker.gitee.io/blog/2021/06/19/%E9%97%AD%E5%8C%85/index.html">
<meta property="og:site_name" content="前端日常">
<meta property="og:description" content="JS中的执行上下文，作用域链和闭包一, 执行上下文概念  当前代码的执行环境 执行上下文的三种类型： 全局执行上下文：全局执行环境是最外围的一个执行环境，在浏览器的全局对象是 window, this指向这个对象 函数执行上下文：可以有无数个，函数被调用的时候会被创建。每次调用函数都会创建一个新的执行上下文。 eval执行上下文，很少用。  每个执行上下文都有三个重要属性 1, 变量对象    2">
<meta property="og:locale" content="zh_CN">
<meta property="og:image" content="https://coloker.gitee.io/images/image-20210615155701776.png">
<meta property="og:image" content="https://coloker.gitee.io/images/image-20210614195259732.png">
<meta property="og:image" content="https://coloker.gitee.io/images/image-20210615105411671.png">
<meta property="article:published_time" content="2021-06-19T08:01:50.000Z">
<meta property="article:modified_time" content="2021-06-19T08:57:59.368Z">
<meta property="article:author" content="王路路">
<meta property="article:tag" content="前端 javascript">
<meta name="twitter:card" content="summary">
<meta name="twitter:image" content="https://coloker.gitee.io/images/image-20210615155701776.png">
  
    <link rel="alternate" href="/blog/atom.xml" title="前端日常" type="application/atom+xml">
  
  
    <link rel="icon" href="/favicon.png">
  
  
  
  
<link rel="stylesheet" href="/blog/css/style.css">

<meta name="generator" content="Hexo 5.4.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/blog/" id="logo">前端日常</a>
      </h1>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"></a>
        
          <a class="main-nav-link" href="/blog/">Home</a>
        
          <a class="main-nav-link" href="/blog/archives">Archives</a>
        
      </nav>
      <!-- <nav id="sub-nav">
        
          <a id="nav-rss-link" class="nav-icon" href="/blog/atom.xml" title="RSS Feed"></a>
        
        <a id="nav-search-btn" class="nav-icon" title="搜索"></a>
      </nav> -->
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="Search"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://coloker.gitee.io/blog"></form>
      </div>
    </div>
  </div>
</header>
      <div class="outer">
        <section id="main"><article id="post-闭包" class="article article-type-post" itemscope itemprop="blogPost">
  <div class="article-meta">
    <a href="/blog/2021/06/19/%E9%97%AD%E5%8C%85/" class="article-date">
  <time datetime="2021-06-19T08:01:50.000Z" itemprop="datePublished">2021-06-19</time>
</a>
    
  <div class="article-category">
    <a class="article-category-link" href="/blog/categories/JavaScript/">JavaScript</a>
  </div>

  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 class="article-title" itemprop="name">
      闭包
    </h1>
  

      </header>
    
    <div class="article-entry" itemprop="articleBody">
      
        <h1 id="JS中的执行上下文，作用域链和闭包"><a href="#JS中的执行上下文，作用域链和闭包" class="headerlink" title="JS中的执行上下文，作用域链和闭包"></a>JS中的执行上下文，作用域链和闭包</h1><h2 id="一-执行上下文"><a href="#一-执行上下文" class="headerlink" title="一, 执行上下文"></a>一, 执行上下文</h2><p><strong>概念</strong>  <strong>当前代码的执行环境</strong></p>
<h4 id="执行上下文的三种类型："><a href="#执行上下文的三种类型：" class="headerlink" title="执行上下文的三种类型："></a><strong>执行上下文的三种类型</strong>：</h4><ol>
<li>全局执行上下文：全局执行环境是最外围的一个执行环境，在浏览器的全局对象是 window, this指向这个对象</li>
<li>函数执行上下文：可以有无数个，函数被<strong>调用</strong>的时候会被创建。每次调用函数都会创建一个新的执行上下文。</li>
<li>eval执行上下文，很少用。</li>
</ol>
<p><strong>每个执行上下文都有三个重要属性</strong></p>
<p>1, 变量对象    2, 作用域链    3, this</p>
<h4 id="执行上下文的生命周期：创建-gt-执行-gt-回收"><a href="#执行上下文的生命周期：创建-gt-执行-gt-回收" class="headerlink" title="执行上下文的生命周期：创建 ==&gt; 执行==&gt; 回收"></a><strong>执行上下文的生命周期：创建 ==&gt; 执行==&gt; 回收</strong></h4><ol>
<li><p><strong>创建阶段</strong></p>
<ul>
<li><p>创建变量对象</p>
<ul>
<li>初始化函数的arguments</li>
<li>函数声明</li>
<li>变量声明</li>
</ul>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">getName</span>(<span class="params">name</span>) </span>&#123;</span><br><span class="line">    <span class="keyword">var</span> b = <span class="number">2</span>;</span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line">    <span class="keyword">var</span> bar = <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;&#125;;</span><br><span class="line"></span><br><span class="line">&#125;</span><br><span class="line">getName(<span class="string">&#x27;qin&#x27;</span>)</span><br><span class="line"></span><br><span class="line">变量对象 = &#123;</span><br><span class="line">    <span class="attr">arguments</span>: &#123;</span><br><span class="line">        <span class="number">0</span>: <span class="string">&#x27;qin&#x27;</span>,</span><br><span class="line">        <span class="attr">length</span>: <span class="number">1</span></span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">name</span>: <span class="string">&#x27;qin&#x27;</span>,</span><br><span class="line">    <span class="attr">b</span>: <span class="literal">undefined</span>,</span><br><span class="line">    <span class="attr">foo</span>: reference to <span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>)</span>&#123;&#125;,</span><br><span class="line">    <span class="attr">bar</span>: <span class="literal">undefined</span></span><br><span class="line">&#125;</span><br></pre></td></tr></table></figure></li>
<li><p>创建作用域链</p>
<p>作用域链是在变量对象之后创建，它本身包含变量对象。作用域链它主要用于变量解析。当要解析变量时，首先从变量所在的作用域进行查找，如果所在作用域没有，则沿着作用域链，查找父级作用域中是否存在该变量，如果没有紧接着向上进行查找直到找到全局作用域为止。</p>
</li>
<li><p>确定this的指向</p>
<p>this指向会包含很多种情况。在全局执行上下文中this总是指向全局对象，如浏览器环境下this指向window。而在函数执行上下文中this的指向取决于函数的调用方式，如果是被一个对象调用那么this指向这个对象，否则一般this是指向window或者在严格模式下，this指向undefined。</p>
</li>
</ul>
</li>
<li><h5 id="执行阶段"><a href="#执行阶段" class="headerlink" title="执行阶段"></a><strong>执行阶段</strong></h5><p>执行变量赋值，代码执行</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">let</span> a = <span class="string">&#x27;javascript&#x27;</span>;</span><br><span class="line"></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">foo</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;foo&#x27;</span>);</span><br><span class="line">    bar();</span><br><span class="line">&#125;</span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">bar</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(<span class="string">&#x27;bar&#x27;</span>);</span><br><span class="line">&#125;</span><br><span class="line">foo();</span><br></pre></td></tr></table></figure>



<p><img src="/images/image-20210615155701776.png" alt="image-20210615155701776"></p>
<ol>
<li>上述代码在浏览器加载时，JavaScript 引擎创建了一个全局执行上下文并把它压入到当前执行栈。</li>
<li>当遇到 <code>foo()</code> 函数调用时， JavaScript 引擎创建了一个 foo 函数执行上下文并把它压入到当前执行栈的顶部。</li>
<li>当从 <code>foo()</code> 函数内部调用 <code>bar()</code> 函数时，JavaScript 引擎创建了一个 bar 函数执行上下文并把它压入到当前执行栈的顶部。</li>
<li>当函数 bar 执行完毕，它的执行上下文会从当前栈中弹出，控制流程到达下一个执行上下文，即 <code>foo()</code> 函数的执行上下文。</li>
<li>当 foo() 执行完成，它的执行上下文从栈弹出，控制流程到达全局执行上下文，一旦所有代码执行完成，javaScript 引擎就从当前栈中移除全局执行上下文。</li>
</ol>
</li>
<li><h5 id="回收阶段"><a href="#回收阶段" class="headerlink" title="回收阶段"></a><strong>回收阶段</strong></h5><p>执行上下文出栈被垃圾回收机制进行回收</p>
</li>
</ol>
<h2 id="二，什么是作用域链"><a href="#二，什么是作用域链" class="headerlink" title="二，什么是作用域链"></a>二，什么是作用域链</h2><p><strong>1.什么是作用域？</strong> <strong>什么是词法作用域</strong>？</p>
<p><strong>作用域</strong>是查找变量（去哪找，怎么找）的一套规则。<strong>词法作用域</strong>在写代码的时候就确认了。js是基于词法作用域的语言，通过定义变量的位置就知道变量的作用域</p>
<p><strong>2.什么是作用域链</strong></p>
<p>​    当某个函数第一次被调用时，会创建一个执行环境及相应的作用域链，并把作用域链赋值给一个特殊的内部属性[[Scopes]]。然后，使用this, arguments 和其他命名参数的值来初始化函数的活动对象。但在作用域中，外部函数的活动对象始终处于第二位，外部函数的外部函数的活动对象处于第三位，…直至作用域链终点的全局执行环境</p>
<p><img src="/images/image-20210614195259732.png" alt="image-20210614195259732"></p>
<p>以上代码涉及三个上下文：全局上下文，foo()的局部上下文，bar()的局部上下文</p>
<p>简单来说，<code>JS</code>引擎进入代码后，会创建变量对象的一个的作用域链，以此保证对执行环境有权访问的所有变量和函数的有序访问。在进入函数后，会创建函数执行环境，并创建相应的变量对象，把我们的变量对象推入到作用域链的前端，作用域链的下一个结点保存的是外部环境的变量对象，作用域链的底端则是全局执行环境的变量对象</p>
<p>上面的例子可以叫做静态作用域链</p>
<p><strong>为什么叫“静态”呢？</strong></p>
<p>因为这样的嵌套关系是分析代码就可以得出的，不需要运行，按照这种顺序访问变量的链就是静态作用域链，这种链的好处是可以直观的知道变量之间的引用关系。</p>
<p>相对的，还有动态作用域链，也就是作用域的引用关系与嵌套关系无关，与执行顺序有关，会在执行的时候动态创建不同函数、块的作用域的引用关系。缺点就是不直观，没法静态分析。</p>
<p>JavaScript 除了静态作用域链外，还有一个特点就是函数可以作为返回值。比如</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">func</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> obj =&#123;</span><br><span class="line">      <span class="attr">name</span>: <span class="string">&#x27;qin&#x27;</span>,</span><br><span class="line">      <span class="attr">age</span>: <span class="number">18</span></span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">const</span> a = <span class="number">100</span>;</span><br><span class="line">  <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="built_in">console</span>.log(a);</span><br><span class="line">  &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> f2 = func();</span><br><span class="line">这就导致了一个问题，本来按照顺序创建调用一层层函数，按顺序创建和销毁作用域挺好的，但是如果内层函数返回了或者通过别的暴露出去了，那么外层函数销毁，内层函数却没有销毁，这时候怎么处理作用域，父作用域销不销毁？ （比如这里的 func 调用结束要不要销毁作用域）</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<p><img src="/images/image-20210615105411671.png" alt="image-20210615105411671"></p>
<h2 id="三，闭包的设计"><a href="#三，闭包的设计" class="headerlink" title="三，闭包的设计"></a>三，闭包的设计</h2><p><strong>概念：闭包就是指有权访问另一个函数作用域中的变量的函数</strong></p>
<p><strong>闭包是通过改变JS回收机制保留某段作用域的一种手段</strong></p>
<p>考虑一下怎么解决这个静态作用域链中的父作用域先于子作用域销毁怎么解决。</p>
<figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> name = <span class="string">&#x27;qinguangli&#x27;</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fun</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">const</span> qin = <span class="string">&#x27;qin&#x27;</span></span><br><span class="line">  <span class="function"><span class="keyword">function</span> <span class="title">fun2</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">const</span> guang = <span class="string">&#x27;guang&#x27;</span></span><br><span class="line">    <span class="function"><span class="keyword">function</span> <span class="title">fun3</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">const</span> li = <span class="string">&#x27;li&#x27;</span></span><br><span class="line">      <span class="built_in">console</span>.log(qin, guang, li)</span><br><span class="line">    &#125;</span><br><span class="line">    <span class="keyword">return</span> fun3</span><br><span class="line">  &#125;</span><br><span class="line">  <span class="keyword">return</span> fun2</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> fun4 = fun()</span><br><span class="line"><span class="keyword">const</span> fun5 = fun4()</span><br><span class="line"><span class="built_in">console</span>.dir(fun5)</span><br><span class="line">fun5()</span><br><span class="line">----------------------------------------------------------------</span><br><span class="line">父作用域有很多跟子涵数无关，肯定不能因为子函数没结束就一直常驻内存。这样肯定有性能问题，所以还是要销毁。 但是销毁了父作用域不能影响子函数，所以要再创建个对象，要把子函数内引用（refer）的父作用域的变量打包里来，给子函数打包带走。</span><br><span class="line">[[Scopes]] ，用这个来放函数打包带走的用到的环境。</span><br><span class="line">我们所考虑的这个解决方案：销毁父作用域后，把用到的变量包起来，打包给子函数，放到一个属性上。这就是闭包的机制。</span><br><span class="line"></span><br></pre></td></tr></table></figure>

<h2 id="四，闭包的使用场景"><a href="#四，闭包的使用场景" class="headerlink" title="四，闭包的使用场景"></a>四，闭包的使用场景</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br></pre></td><td class="code"><pre><span class="line"><span class="keyword">var</span> fun = (<span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">  <span class="keyword">var</span> name = <span class="string">&#x27;qin&#x27;</span></span><br><span class="line">  <span class="keyword">return</span> &#123;</span><br><span class="line">    <span class="attr">getName</span>: <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">      <span class="keyword">return</span> name</span><br><span class="line">    &#125;,</span><br><span class="line">    <span class="attr">changeName</span>: <span class="function"><span class="keyword">function</span> (<span class="params">newName</span>) </span>&#123;</span><br><span class="line">      name = newName</span><br><span class="line">    &#125;</span><br><span class="line">  &#125;</span><br><span class="line">&#125;())</span><br><span class="line">fun.getName() <span class="comment">// 得到qin</span></span><br><span class="line">fun.name <span class="comment">// type error</span></span><br><span class="line">fun.changeName(<span class="string">&#x27;qinguangli&#x27;</span>)</span><br><span class="line">fun.getName()</span><br><span class="line"><span class="built_in">console</span>.log(fun.getName())   <span class="comment">// 通过闭包实现公共变量，私有变量</span></span><br><span class="line">-----------------------------------------------------------------</span><br><span class="line">    </span><br></pre></td></tr></table></figure>

<h2 id="五，闭包的缺点"><a href="#五，闭包的缺点" class="headerlink" title="五，闭包的缺点"></a>五，闭包的缺点</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br></pre></td><td class="code"><pre><span class="line">JavaScript 是静态作用域的设计，闭包是为了解决子函数晚于父函数销毁的问题，我们会在父函数销毁时，把子函数引用到的变量打成 Closure 包放到函数的 [[Scopes]] 上，让它计算父函数销毁了也随时随地能访问外部环境。</span><br><span class="line">父函数销毁，栈帧对应的内存马上释放，而返回的函数会把作用域链过滤出用到的引用形成闭包链放在堆中。 这就导致了一个隐患： 如果一个很大的对象被函数引用，本来函数调用结束就能销毁，但是现在引用却被通过闭包保存到了堆里，而且还一直用不到，那这块堆内存就一直没法使用，严重到一定程度就算是内存泄漏了。</span><br><span class="line"></span><br></pre></td></tr></table></figure>



<h4 id="作用域与执行上下文的关系"><a href="#作用域与执行上下文的关系" class="headerlink" title="作用域与执行上下文的关系"></a><strong>作用域与执行上下文</strong>的关系</h4><p>javascript的执行分为：解释和执行两个阶段</p>
<p>解释阶段</p>
<ul>
<li>词法分析</li>
<li>语法分析</li>
<li>作用域确定规则</li>
</ul>
<p>执行阶段</p>
<ul>
<li>创建执行上下文</li>
<li>执行代码函数</li>
<li>垃圾回收</li>
</ul>
<p><strong>作用域在函数定义时就已经确定了，而不是在函数调用时确定，但执行上下文是函数执行之前创建的。</strong></p>
<h2 id="延伸函数的生命周期"><a href="#延伸函数的生命周期" class="headerlink" title="延伸函数的生命周期"></a>延伸函数的生命周期</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">fn</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> a = <span class="number">1</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(++a)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> result = fn()</span><br><span class="line"><span class="keyword">const</span> result1 = fn()</span><br><span class="line">result()</span><br><span class="line">result() </span><br><span class="line">result1()</span><br><span class="line">result1()</span><br></pre></td></tr></table></figure>

<h2 id="在构造函数中作用域的使用"><a href="#在构造函数中作用域的使用" class="headerlink" title="在构造函数中作用域的使用"></a>在构造函数中作用域的使用</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">Person</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">    <span class="keyword">let</span> num = <span class="number">1</span></span><br><span class="line">    <span class="built_in">this</span>.add = <span class="function"><span class="keyword">function</span> (<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="built_in">console</span>.log(++num)</span><br><span class="line">    &#125;</span><br><span class="line">&#125;</span><br><span class="line"><span class="keyword">const</span> p = <span class="keyword">new</span> Person()</span><br><span class="line">p.add()</span><br><span class="line">p.add()</span><br></pre></td></tr></table></figure>

<h2 id="在项目中的使用场景"><a href="#在项目中的使用场景" class="headerlink" title="在项目中的使用场景"></a>在项目中的使用场景</h2><figure class="highlight js"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br></pre></td><td class="code"><pre><span class="line">函数防抖</span><br><span class="line"><span class="comment">/*</span></span><br><span class="line"><span class="comment">* fn [function] 需要防抖的函数</span></span><br><span class="line"><span class="comment">* delay [number] 毫秒，防抖期限值</span></span><br><span class="line"><span class="comment">*/</span></span><br><span class="line"><span class="function"><span class="keyword">function</span> <span class="title">debounce</span>(<span class="params">fn,delay</span>)</span>&#123;</span><br><span class="line">    <span class="keyword">let</span> timer = <span class="literal">null</span></span><br><span class="line">    <span class="comment">//借助闭包</span></span><br><span class="line">    <span class="keyword">return</span> <span class="function"><span class="keyword">function</span>(<span class="params"></span>) </span>&#123;</span><br><span class="line">        <span class="keyword">if</span>(timer)&#123;</span><br><span class="line">            <span class="built_in">clearTimeout</span>(timer) <span class="comment">//进入该分支语句，说明当前正在一个计时过程中，并且又触发了相同事件。所以要取消当前的计时，重新开始计时</span></span><br><span class="line">            timer = setTimeOut(fn,delay) </span><br><span class="line">        &#125;<span class="keyword">else</span>&#123;</span><br><span class="line">            timer = setTimeOut(fn,delay) <span class="comment">// 进入该分支说明当前并没有在计时，那么就开始一个计时</span></span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br></pre></td></tr></table></figure>


      
    </div>
    <footer class="article-footer">
      <a data-url="https://coloker.gitee.io/blog/2021/06/19/%E9%97%AD%E5%8C%85/" data-id="ckq3tmkt70003ksnr3w5rgtc4" class="article-share-link bdsharebuttonbox" data-cmd="more">分享</a>
      <script>window._bd_share_config={"common":{"bdSnsKey":{},"bdText":"","bdMini":"1","bdMiniList":false,"bdPic":"","bdStyle":"2","bdSize":"16"},"share":{}};with(document)0[(getElementsByTagName('head')[0]||body).appendChild(createElement('script')).src='http://bdimg.share.baidu.com/static/api/js/share.js?v=89860593.js?cdnversion='+~(-new Date()/36e5)];</script>
      
      
    </footer>
  </div>
  
    
<nav id="article-nav">
  
    <a href="/blog/2021/06/19/promise/" id="article-nav-newer" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Newer</strong>
      <div class="article-nav-title">
        
          promise
        
      </div>
    </a>
  
  
    <a href="/blog/2021/06/19/hello-world/" id="article-nav-older" class="article-nav-link-wrap">
      <strong class="article-nav-caption">Older</strong>
      <div class="article-nav-title">自我介绍</div>
    </a>
  
</nav>

  
</article>

</section>
        
          <aside id="sidebar">
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">分类</h3>
    <div class="widget">
      <ul class="category-list"><li class="category-list-item"><a class="category-list-link" href="/blog/categories/JavaScript/">JavaScript</a></li><li class="category-list-item"><a class="category-list-link" href="/blog/categories/Start/">Start</a></li></ul>
    </div>
  </div>


  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/blog/archives/2021/06/">六月 2021</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/blog/2021/06/19/promise/">promise</a>
          </li>
        
          <li>
            <a href="/blog/2021/06/19/%E9%97%AD%E5%8C%85/">闭包</a>
          </li>
        
          <li>
            <a href="/blog/2021/06/19/hello-world/">自我介绍</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      &copy; 2021 王路路<br>
      邮箱：wanglulugg@gmail.com<br />
    </div>
  </div>
</footer>
    </div>
    <nav id="mobile-nav">
  
    <a href="/blog/" class="mobile-nav-link">Home</a>
  
    <a href="/blog/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    

<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>


  
<link rel="stylesheet" href="/blog/fancybox/jquery.fancybox.css">

  
<script src="/blog/fancybox/jquery.fancybox.pack.js"></script>




<script src="/blog/js/script.js"></script>




  </div>
</body>
</html>